import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

// 设计思路：观察者模式接口，用于消息广播
// 每个客户端作为观察者，当有新消息时会收到通知
interface MessageObserver {
    void onMessageReceived(String message);
}

// 设计思路：消息广播主题类，实现观察者模式
// 负责管理所有客户端观察者，并将消息广播给所有订阅者
class MessageBroadcaster {
    private List<MessageObserver> observers = new ArrayList<>();

    // 添加观察者（新连接的客户端）
    public void subscribe(MessageObserver observer) {
        observers.add(observer);
    }

    // 移除观察者（客户端断开连接时）
    public void unsubscribe(MessageObserver observer) {
        observers.remove(observer);
    }

    // 广播消息给所有观察者
    public void broadcast(String message) {
        for (MessageObserver observer : observers) {
            observer.onMessageReceived(message);
        }
    }
}

// 设计思路：客户端处理类，负责处理单个客户端的读写操作
// 实现MessageObserver接口以接收广播消息
// 使用StringBuilder累积消息片段，直到遇到换行符
class ClientHandler implements MessageObserver {
    private SocketChannel clientChannel;
    private ByteBuffer buffer = ByteBuffer.allocate(1024);
    private StringBuilder messageBuilder = new StringBuilder();

    public ClientHandler(SocketChannel clientChannel) {
        this.clientChannel = clientChannel;
    }

    public SocketChannel getChannel() {
        return clientChannel;
    }

    // 读取客户端发送的消息
    // 设计思路：使用ByteBuffer读取数据，遇到换行符时解析完整消息并广播
    public void read(SelectionKey key) throws IOException {
        buffer.clear();
        int bytesRead = clientChannel.read(buffer);

        if (bytesRead == -1) {
            // 客户端断开连接，取消注册并关闭通道
            key.cancel();
            clientChannel.close();
            return;
        }

        buffer.flip();
        while (buffer.hasRemaining()) {
            char c = (char) buffer.get();
            if (c == '\n') {
                String message = messageBuilder.toString().trim();
                if (!message.isEmpty()) {
                    // 广播完整消息
                    ((MessageBroadcaster) key.attachment()).broadcast(message);
                }
                messageBuilder.setLength(0);
            } else {
                messageBuilder.append(c);
            }
        }
    }

    // 实现观察者接口，接收广播消息并发送给客户端
    @Override
    public void onMessageReceived(String message) {
        try {
            String formattedMessage = message + "\n";
            ByteBuffer writeBuffer = ByteBuffer.wrap(formattedMessage.getBytes(StandardCharsets.UTF_8));
            clientChannel.write(writeBuffer);
        } catch (IOException e) {
            System.err.println("Error sending message to client: " + e.getMessage());
        }
    }
}

// 设计思路：主服务器类，使用NIO Selector实现非阻塞I/O
// 负责接受新连接、处理客户端消息、协调消息广播
public class NIOMessagingServer {
    private static final int PORT = 8080;
    private Selector selector;
    private ServerSocketChannel serverSocket;
    private MessageBroadcaster broadcaster;

    // 初始化服务器
    // 设计思路：配置非阻塞ServerSocketChannel，注册到Selector监听连接事件
    public NIOMessagingServer() throws IOException {
        selector = Selector.open();
        serverSocket = ServerSocketChannel.open();
        serverSocket.configureBlocking(false);
        serverSocket.bind(new InetSocketAddress(PORT));
        serverSocket.register(selector, SelectionKey.OP_ACCEPT);
        broadcaster = new MessageBroadcaster();
    }

    // 启动服务器主循环
    // 设计思路：使用Selector轮询事件，处理新连接和消息读取
    public void start() throws IOException {
        System.out.println("Server started on port " + PORT);

        while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                if (key.isAcceptable()) {
                    handleAccept(key);
                } else if (key.isReadable()) {
                    handleRead(key);
                }

                keyIterator.remove();
            }
        }
    }

    // 处理新客户端连接
    // 设计思路：接受新连接，配置非阻塞，自动订阅广播频道
    private void handleAccept(SelectionKey key) throws IOException {
        ServerSocketChannel server = (ServerSocketChannel) key.channel();
        SocketChannel client = server.accept();
        client.configureBlocking(false);

        // 创建客户端处理器并订阅广播
        ClientHandler handler = new ClientHandler(client);
        broadcaster.subscribe(handler);

        // 注册读事件
        client.register(selector, SelectionKey.OP_READ, broadcaster);
        System.out.println("New client connected: " + client.getRemoteAddress());
    }

    // 处理客户端消息读取
    // 设计思路：委托给ClientHandler处理消息读取和解析
    private void handleRead(SelectionKey key) throws IOException {
        ClientHandler handler = new ClientHandler((SocketChannel) key.channel());
        handler.read(key);
    }

    public static void main(String[] args) {
        try {
            NIOMessagingServer server = new NIOMessagingServer();
            server.start();
        } catch (IOException e) {
            System.err.println("Server error: " + e.getMessage());
        }
    }
}